package cn.xiaoming.car.server.service.impl;

import cn.xiaoming.car.pojo.car.pojo.vo.CarListItemVO;
import cn.xiaoming.car.pojo.car.pojo.vo.CarVO;
import cn.xiaoming.car.pojo.order.pojo.entity.OrderTbl;
import cn.xiaoming.car.pojo.order.pojo.param.OrderTblParam;
import cn.xiaoming.car.pojo.order.pojo.param.OrderTblUpdateParam;
import cn.xiaoming.car.pojo.order.pojo.vo.OrderTblVo;
import cn.xiaoming.car.server.ICarService;
import cn.xiaoming.car.server.IOrderService;
import cn.xiaoming.car.server.ex.ServiceException;

import cn.xiaoming.car.server.jsonresult.ServiceCode;
import cn.xiaoming.car.server.pojo.vo.PageData;
import cn.xiaoming.car.server.util.PageInfoToPageDataConverter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.stereotype.Service;
import cn.xiaoming.car.server.mapper.OrderTblMapper;
import org.springframework.web.bind.annotation.PathVariable;


import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;

import javax.rmi.CORBA.Util;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static cn.xiaoming.car.server.jsonresult.ServiceCode.*;

@Slf4j
@Service
@DubboService
public class IOrderImpl implements IOrderService {

    @Autowired
    OrderTblMapper orderTblMapper;
    
    @DubboReference
    ICarService carService;

    @Autowired
    RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Override
    public void addNewOrder(Long carId, Long buyerId) {
        log.debug("开始执行处理添加订单业务车辆id：{}，买家id：{}",carId,buyerId);

        //根据carId要车辆信息
        CarListItemVO carById = carService.getCarById(carId);
        //log.debug("车辆信息：{}",car);
        //检查车辆启用状态
        //Integer enable=1;
        if (carById.getEnable()!=1){
            throw new ServiceException(ERR_BAD_REQUEST,"车辆未启用");
        }

        //查询该车在自己的订单中是否有，count=0 表示没有
        int myCount = orderTblMapper.selectCount(
                Wrappers.<OrderTbl>lambdaQuery()
                        .eq(OrderTbl::getBuyerId,buyerId)
                        .eq(OrderTbl::getCarId, carId)
                        .ne(OrderTbl::getStatus,EXPIRE)
                        .ne(OrderTbl::getStatus,ERR)
        );
        if (myCount>0){
            throw new ServiceException(ERR_BAD_REQUEST,"订单已存在，请勿重复下单");
        }

        //查询该车在订单表中是否已经被支付订金，count=0 表示没有,除去自己
        int count = selectPurchasedCountByCarId(carId,buyerId);
        System.out.println(count);
        if (count>0){
            throw new ServiceException(ERR_BAD_REQUEST,"车辆已被订购");
        }

        //从车辆信息中获取到卖家id
        Long sellerId =1L; //car.getUserId();
        //获取车辆金额
        BigDecimal price =new BigDecimal(100000); //car.getPrice();
        //默认生成30%的订金金额
        BigDecimal firstPrice=price.multiply(new BigDecimal(0.3));
        //尾款70%
        BigDecimal lastPrice=price.multiply(new BigDecimal(0.7));

        log.debug("生成订单信息");
        OrderTbl orderTbl=new OrderTbl()
                .setId(UUID.randomUUID().toString())
                .setBuyerId(buyerId)
                .setCarId(carId)
                .setSellerId(sellerId)
                .setFirstMoney(firstPrice)
                .setLastMoney(lastPrice)
                .setStatus(INITIAL)
                .setGmtFirstMoney(null)
                .setGmtLastMoney(null)
                .setGmtCreate(LocalDateTime.now())
                .setGmtOver(null);

        //应该先存redis，支付的时候先读取redis中有没有信息，没有的话就是订单已经过期，
        String orderRedisKey=ORDER_KEY_+orderTbl.getId();//定义订单的key
        redisTemplate.opsForValue().set(orderRedisKey,orderTbl);
        log.debug("已经向redis中存消息");

        //1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
        //发送延时消费的消息，并且在消费时先删除redis中的信息
        Message<String> message= MessageBuilder.withPayload(orderRedisKey)
                .setHeader(RocketMQHeaders.TRANSACTION_ID,orderRedisKey).build();
        SendResult a = rocketMQTemplate.syncSend("expire-order", message,3000,16);
        log.debug("发送延时消息的结果：{}",a);

        log.debug("准备插入数据库");
        int insert = orderTblMapper.insert(orderTbl);
        if (insert!=1){
            // 抛出未知异常
            throw new ServiceException(ERR_INSERT,"未知的订单生成错误");
        }
        log.debug("添加订单完成");
    }

    //删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删删

    @Override
    public void deleteById(String id) {
        log.debug("开始执行处理删除订单业务订单id：{}",id);
        orderTblMapper.deleteById(id);
        log.debug("删除订单业务完成");
    }


    //改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改改


    @Override
    public void updateInfoById(Long userId,String orderId,String status){
        OrderTbl orderTbl = orderTblMapper.selectById(orderId);
        if (orderTbl==null){
            throw new ServiceException(ERR_NOT_FOUND,"订单不存在");
        }else if ("DEPARTED".equals(status)&&orderTbl.getStatus()==PAID_LAST&&orderTbl.getSellerId()==userId){
            orderTbl.setStatus(DEPARTED);
            orderTblMapper.updateById(orderTbl);
        }else if ("RECEIVED".equals(status)&&orderTbl.getStatus()==DEPARTED&&orderTbl.getBuyerId()==userId){
            orderTbl.setStatus(RECEIVED);
            orderTblMapper.updateById(orderTbl);
        } else {
            throw new ServiceException(ERR_BAD_REQUEST,"请求错误，无权操作，滚！");
        }
    }

    @Override
    public void updateOrderTbl(OrderTbl orderTbl){
        int i = orderTblMapper.updateById(orderTbl);
        if (i!=1){
            throw new ServiceException(ERR_UPDATE,"更新数据失败！");
        }
    }


    @Override
    public void updateInfo(OrderTblUpdateParam orderTblUpdateParam) {
        log.debug("根据id更新订单信息业务！！！！,参数：{}",orderTblUpdateParam);
        OrderTbl orderTbl=new OrderTbl();
        BeanUtils.copyProperties(orderTblUpdateParam,orderTbl);
        int i = orderTblMapper.updateById(orderTbl);
        if (i!=1){
            throw new ServiceException(ERR_UNKNOWN,"订单数据更新失败，未知！！！！");
        }
        log.debug("根据id更新订单信息业务结束！！！！");
    }

    //查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查查

    @Override
    public int selectPurchasedCountByCarId(Long carId, Long buyId){
        //查询该车在订单表中是否已经被支付购买，count=0 表示没有
        return orderTblMapper.selectCount(
                Wrappers.<OrderTbl>lambdaQuery()
                        .eq(OrderTbl::getCarId, carId)
                        .ne(OrderTbl::getBuyerId,buyId)
                        .ne(OrderTbl::getStatus,INITIAL)
                        .ne(OrderTbl::getStatus,ERR)
                        .ne(OrderTbl::getStatus,EXPIRE));
    }

    @Override
    public PageData<OrderTblVo> selectListByUserId(Long id, Integer num,String type) {
//        List<OrderTbl> orderTbls = orderTblMapper.selectList(Wrappers.<OrderTbl>lambdaQuery().eq(OrderTbl::getBuyerId, id));
//        Page<OrderTbl> page = new Page(num,7);
//        Page<OrderTbl> orderTblPage = orderTblMapper.selectPage(page, Wrappers.<OrderTbl>lambdaQuery().eq(OrderTbl::getBuyerId, id));

        log.debug("开始执行处理根据用户id查询订单业务 用户id：{}，查询页码：{}",id,num);
        PageHelper.startPage(num, 8);
        List<OrderTblVo> list =new ArrayList<>();
        if (type.equals("seller")){
            list = orderTblMapper.selectListBySellerId(id);
        }else if (type.equals("buyer")){
            list =orderTblMapper.selectListByBuyerId(id);
        }

        PageInfo<OrderTblVo> pageInfo = new PageInfo<>(list);
        PageData<OrderTblVo> pageData = PageInfoToPageDataConverter.convert(pageInfo);
        log.debug("查询完成，即将返回：{}", pageData.getList());
        return pageData;
    }

    @Override
    public PageData<OrderTblVo> selectList(Integer pageNum) {
        Integer pageSize = 8;
        return selectList(pageNum, pageSize);
    }

    @Override
    public PageData<OrderTblVo> selectList(Integer pageNum, Integer pageSize) {
        log.debug("开始处理【查询订单列表】的业务，页码：{}，每页记录数：{}", pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<OrderTblVo> list = orderTblMapper.list();
        PageInfo<OrderTblVo> pageInfo = new PageInfo<>(list);
        PageData<OrderTblVo> pageData = PageInfoToPageDataConverter.convert(pageInfo);
        log.debug("查询完成，即将返回：{}", pageData.getList());
        return pageData;
    }

    @Override
    public OrderTbl selectOrderById(String uuid) {
        OrderTbl orderTbl = orderTblMapper.selectById(uuid);
        if (orderTbl==null){
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"找不到该订单信息");
        }
        return orderTbl;
    }


}
